#include "NetPeer.h"
#include "NetPacket.h"
#include "ReliableChannel.h"
#include "SequencedChannel.h"
#include "NetPacketPool.h"
#include "NetConstants.h"
#include "NetManager.h"
#include "NetUtils.h"
#include "NetConnectRequestPacket.h"
#include "NetDebug.h"
#include "spdlog/spdlog.h"

namespace LiteNetLib
{
    const int32_t MtuCheckDelay = 3000;
    const int32_t MaxMtuCheckAttempts = 4;
    // =========================================== [ IncomingFragments ] ===========================================

    IncomingFragments::IncomingFragments(int32_t size) : fragments(size, nullptr), receivedCount(0), totalSize(0){}

    IncomingFragments::~IncomingFragments()
    {
        for(int32_t index = 0; index < fragments.size(); index++)
        {
            if(fragments[index] != nullptr)
            {
                delete fragments[index];
                fragments[index] = nullptr;
            }
        }
    }

    void IncomingFragments::clear()
    {
        for(int32_t index = 0; index < fragments.size(); index++)
        {
            if(fragments[index] != nullptr)
            {
                NetPacketPool::GetInstance().recycleOrDelete(fragments[index]);
                fragments[index] = nullptr;
            }
        }
    }


    // ================================================= [ NetPeer ] =================================================

    NetPeer::NetPeer(NetManager *netManager, net_endpoint *endpoint) :
        m_netManager(netManager),
        m_timeSinceLastPacket(0), 
        m_fragmentID(0), 
        m_mtuCheckTime(0),
        m_mtuCheckAttempts(0),
        m_finishMtu(false),
        m_channels(256, nullptr) ,
        m_mergePos(0),
        m_mergeCount(0),
        m_pingSendTime(0)
    {
        m_mergePacket = new NetPacket(PacketProperty::Merged,NetConstants::MaxPacketSize);
        m_pongPacket  = new NetPacket(PacketProperty::Pong, 0);
        m_pingPacket  = new NetPacket(PacketProperty::Ping, 0);

        if (m_netManager->mtuOverride > 0)
        {
            overrideMtu(m_netManager->mtuOverride);
        }
        else if (m_netManager->useSafeMtu)
        {
            setMtu(0);
        }
        else
        {
            setMtu(1);
        }
        m_hashCode = NetUtils::SockHashCode(endpoint);
        m_address = NetUtils::GetAddressStr(endpoint);
        m_endpoint = *endpoint;
    }

    NetPeer::NetPeer(NetManager *netManager, net_endpoint *endpoint, int64_t connectId, uint8_t connectNum) : NetPeer(netManager, endpoint)
    {
        m_connectTime = connectId;
        m_connectionState = ConnectionState::Connected;

        setConnectionNum(connectNum);
        //Make initial packet
        m_connectAcceptPacket = NetConnectAcceptPacket::Make(m_connectTime, connectNum, false);
        //Send
        m_netManager->sendNetPacket(m_connectAcceptPacket, &m_endpoint);

        // NetDebug::Info("[CC] ConnectId: {}", m_connectTime);
    }

    NetPeer::~NetPeer()
    {
        // 清理通道资源
        for(int32_t index = 0; index < m_channels.size(); index++)
        {
            if(m_channels[index] != nullptr)
            {
                m_channels[index]->clear();
                delete m_channels[index];
                m_channels[index] = nullptr;
            }
        }
        // 清理遗留的碎片资源
        for(auto it = m_holdeFragments.begin(); it != m_holdeFragments.end(); ++it)
        {
            if(it->second != nullptr)
            {
                it->second->clear();
                delete it->second;
                it->second = nullptr;
            }
        }
        if(m_mergePacket != nullptr)
        {
            delete m_mergePacket;
            // NetPacketPool::GetInstance().recycleOrDelete(m_mergePacket);
        }
        if(m_pongPacket != nullptr)
        {
            delete m_pongPacket;
            // NetPacketPool::GetInstance().recycleOrDelete(m_pongPacket);
        }
        if(m_pingPacket != nullptr)
        {
            delete m_pingPacket;
            // NetPacketPool::GetInstance().recycleOrDelete(m_pingPacket);
        }
        if (m_connectAcceptPacket != nullptr)
        {
            delete m_connectAcceptPacket;
            // NetPacketPool::GetInstance().recycleOrDelete(m_connectAcceptPacket);
        }
        if (m_shutdownPacket != nullptr)
        {
            delete m_shutdownPacket;
            // NetPacketPool::GetInstance().recycleOrDelete(m_shutdownPacket);
        }

        // NetDebug::Info("~NetPeer()");
    }

    void NetPeer::setConnectionNum(uint8_t num)
    {
        m_connectNum = num;
        m_mergePacket->setConnectionNumber(num);
        m_pongPacket->setConnectionNumber(num);
        m_pingPacket->setConnectionNumber(num);
    }

    /***********************************************************************************************************
     * @brief 按档位设置最大的传输单元，也就是发包时，包的最大字节数
     * @param mtuIdx 传输挡位 0~6
    ***********************************************************************************************************/
    void NetPeer::setMtu(uint8_t mtuIdx)
    {
        if(mtuIdx < 7)
        {
            m_mtuIdx = mtuIdx;
            m_mtu = NetConstants::PossibleMtu[mtuIdx];
        }
    }

    /***********************************************************************************************************
     * @brief 设置最大的传输单元，也就是发包时，包的最大字节数
     * @param value 每个包最大的字节数
    ***********************************************************************************************************/
    void NetPeer::overrideMtu(int32_t value)
    {
        m_mtu = value;
        m_finishMtu = true;
    }

    /***********************************************************************************************************
     * @brief 创建通道，并将通道存放在缓存中，若缓存中有对应id的通道，则是会复用，而不是新建通道
     * @param idx 通道ID
    ***********************************************************************************************************/
    BaseChannel *NetPeer::createChannel(uint8_t idx)
    {
        std::lock_guard<std::mutex> lk(m_createChannelMutex);
        BaseChannel *newChannel = m_channels[idx];
        if (newChannel != nullptr)
        {
            return newChannel;
        }
        switch ((DeliveryMethod)(idx % 4))
        {
        case DeliveryMethod::ReliableUnordered:
            newChannel = new ReliableChannel(this, false, idx);
            break;
        case DeliveryMethod::Sequenced:
            newChannel = new SequencedChannel(this, false, idx);
            break;
        case DeliveryMethod::ReliableOrdered:
            newChannel = new ReliableChannel(this, true, idx);
            break;
        case DeliveryMethod::ReliableSequenced:
            newChannel = new SequencedChannel(this, true, idx);
            break;
        }
        m_channels[idx] = newChannel;
        return newChannel;
    }

    void NetPeer::reject(int64_t connectionId, uint8_t connectionNumber, const char *rejectData, uint32_t dataLength)
    {
        m_connectTime = connectionId;
        m_connectNum = connectionNumber;
        shutdown(rejectData, dataLength, false);
    }

    void NetPeer::disconnect(const char *disconnectData, uint32_t dataLength)
    {
        NetDebug::Debug("主动断开 {} | {} 的连接", getAddress(), m_hashCode);
        m_netManager->disconnectPeer(shared_from_this(), disconnectData, dataLength);
    }

    void NetPeer::disconnect()
    {
        NetDebug::Debug("主动断开 {} | {} 的连接", getAddress(), m_hashCode);
        m_netManager->disconnectPeer(shared_from_this());
    }

    DisconnectResult NetPeer::processDisconnect(const char *dataBuff, uint32_t dataSize)
    {
        if((m_connectionState == ConnectionState::Connected || m_connectionState == ConnectionState::Outgoing) && 
            dataSize >= 9 && 
            NetUtils::ByteToInt64(dataBuff + 1) == m_connectTime &&
            NetPacket::GetConnectionNumber(dataBuff) == m_connectNum)
        {
            return (m_connectionState == ConnectionState::Connected ? DisconnectResult::Disconnect : DisconnectResult::Reject);
        }
        return DisconnectResult::None;
    }


    ShutdownResult NetPeer::shutdown(const char *shutdownData, uint32_t dataLength, bool force)
    {
        std::lock_guard<std::mutex> lk(m_shutdownMutex);
        //trying to shutdown already disconnected
        if (m_connectionState == ConnectionState::Disconnected || m_connectionState == ConnectionState::ShutdownRequested)
        {
            return ShutdownResult::None;
        }
        ShutdownResult result = (m_connectionState == ConnectionState::Connected ? ShutdownResult::WasConnected : ShutdownResult::Success);

        //don't send anything
        if (force)
        {
            m_connectionState = ConnectionState::Disconnected;
            return result;
        }
        
        //reset time for reconnect protection
        m_timeSinceLastPacket = 0;
        m_shutdownPacket = new NetPacket(PacketProperty::Disconnect, dataLength);
        m_shutdownPacket->setConnectionNumber(m_connectNum);
        NetUtils::Int64ToByte(&(m_shutdownPacket->getRawData()[1]), m_connectTime);
        if (m_shutdownPacket->getPacketSize() >= m_mtu)
        {
            NetDebug::Error("[Peer] Disconnect additional data size more than MTU - 8!");
        }
        else
        {
            memcpy(m_shutdownPacket->getRawData() + 9, shutdownData, dataLength);
        }
        m_connectionState = ConnectionState::ShutdownRequested;
        // NetDebug::Info("[Peer] Send disconnect");
        m_netManager->sendNetPacket(m_shutdownPacket, &m_endpoint);
        return result;
    }

    void NetPeer::updateRoundTripTime(int32_t roundTripTime)
    {
        m_rtt += roundTripTime;
        m_rttCount++;
        m_avgRtt = m_rtt / m_rttCount;
        m_resendDelay = 25.0 + m_avgRtt * 2.1;
    }

    /***********************************************************************************************************
     * @brief 收到可靠的包
     * @param method 传输方式
     * @param packet 数据包
     * @note 传入该函数的 数据包 不可delete或回收处理，函数内部已经做了处理
    ***********************************************************************************************************/ 
    void NetPeer::addReliablePacket(DeliveryMethod method, NetPacket *packet)
    {
        if(packet->isFragmented())
        {
            // NetDebug::Info("Fragment. Id: {}, Part: {}, Total: {}", packet->getFragmentId(), packet->getFragmentPart(), packet->getFragmentsTotal());
            // Get needed array from dictionary
            uint16_t packetFragID = packet->getFragmentId();
            IncomingFragments *incomingFragments = nullptr;
            if(m_holdeFragments.find(packetFragID) != m_holdeFragments.end() && m_holdeFragments[packetFragID] != nullptr)
            {
                incomingFragments = m_holdeFragments[packetFragID];
            }
            else
            {
                incomingFragments = new IncomingFragments(packet->getFragmentsTotal());
                incomingFragments->channelID = packet->getChannelId();
                m_holdeFragments[packetFragID] = incomingFragments;
            }
            // 拿到缓存
            auto &fragments = incomingFragments->fragments;
            // 错误规避
            if( packet->getFragmentPart() >= fragments.size() || 
                fragments[packet->getFragmentPart()] != nullptr || 
                packet->getChannelId() != incomingFragments->channelID)
            {
                NetPacketPool::GetInstance().recycleOrDelete(packet);
                return;
            }
            //Fill array
            fragments[packet->getFragmentPart()] = packet;

            //Increase received fragments count
            incomingFragments->receivedCount++;

            //Increase total size
            incomingFragments->totalSize += packet->getPacketSize() - NetConstants::FragmentedHeaderTotalSize;
            
            //Check for finish
            if(incomingFragments->receivedCount != fragments.size())
            {
                NetDebug::Warn("分割包: {},{}", incomingFragments->receivedCount, fragments.size());
                return;
            }
            // 包头偏移
            int32_t pos = 0;

            //just simple packet
            NetPacket *resultingPacket = NetPacketPool::GetInstance().getPacket(incomingFragments->totalSize + pos);
            for(int32_t index = 0; index < incomingFragments->receivedCount; index++)
            {
                NetPacket *fragment = fragments[index];
                int32_t writtenSize = fragment->getPacketSize() - NetConstants::FragmentedHeaderTotalSize;

                if(pos + writtenSize > resultingPacket->getPacketSize())
                {
                    NetDebug::Error("Fragment error pos: {} >= resultPacketSize: {} , totalSize: {}", pos + writtenSize, resultingPacket->getRawDataSize(), incomingFragments->totalSize);
                    incomingFragments->clear();
                    delete incomingFragments;
                    m_holdeFragments[packetFragID] = nullptr;
                    return;
                }

                //Create resulting big packet
                memcpy(&(resultingPacket->getRawData()[pos]), &(fragment->getRawData()[NetConstants::FragmentedHeaderTotalSize]),writtenSize);
                pos += writtenSize;
                //Free memory
                NetPacketPool::GetInstance().recycleOrDelete(fragment);
                fragments[index] = nullptr;
            }

            //Clear memory
            incomingFragments->clear();
            delete incomingFragments;
            m_holdeFragments[packetFragID] = nullptr;

            //Send to process
            m_netManager->createReceiveEvent(resultingPacket, method, 0, shared_from_this());
        }
        else //Just simple packet
        {
            m_netManager->createReceiveEvent(packet, method, NetConstants::ChanneledHeaderSize, shared_from_this());
        }
    }


    /***********************************************************************************************************
     * @brief 处理修改单元数据量的包
     * @param theData 数据包
     * @param dataSize 数据大小
    ***********************************************************************************************************/ 
    void NetPeer::processMtuData(char *theData, uint32_t dataSize)
    {
        if(dataSize < NetConstants::PossibleMtu[0])
        {
            return;
        }
        int32_t receivedMtu = NetUtils::ByteToInt32(&(theData[1]));
        int32_t endMtuCheck = NetUtils::ByteToInt32(&(theData[dataSize - 4]));

        if(receivedMtu != dataSize || receivedMtu != endMtuCheck || receivedMtu > NetConstants::MaxPacketSize)
        {
            return;
        }

        if(NetPacket::GetProperty(theData) == PacketProperty::MtuCheck)
        {
            m_mtuCheckAttempts = 0;
            NetPacket::SetProperty(theData, PacketProperty::MtuOk);
            m_netManager->sendRaw(theData, dataSize, getEndpoint());
        }
        else if(receivedMtu > m_mtu && m_finishMtu == false)
        {
            if(receivedMtu != NetConstants::PossibleMtu[m_mtuIdx + 1])
            {
                return;
            }
            std::lock_guard<std::mutex> lk(m_mtuMutex);
            setMtu(m_mtuIdx + 1);
            if(m_mtuIdx == (sizeof(NetConstants::PossibleMtu) / sizeof(NetConstants::PossibleMtu[0]) - 1))
            {
                m_finishMtu = true;
            }
        }
    }

    /***********************************************************************************************************
     * @brief 更新通道逻辑，扩展单次发包的大小
     * @param deltaTime 时间增量，单位:ms
    ***********************************************************************************************************/ 
    void NetPeer::updateMtuLogic(int32_t deltaTime)
    {
        if(m_finishMtu == true)
        {
            return;
        }
        m_mtuCheckTime += deltaTime;
        if(m_mtuCheckTime < MtuCheckDelay)
        {
            return;
        }
        m_mtuCheckTime = 0;
        m_mtuCheckAttempts++;
        if(m_mtuCheckAttempts >= MaxMtuCheckAttempts)
        {
            m_finishMtu = true;
            return;
        }
        std::lock_guard<std::mutex> lk(m_mtuMutex);
        if(m_mtuIdx >= (sizeof(NetConstants::PossibleMtu) / sizeof(NetConstants::PossibleMtu[0]) - 1))
        {
            return;
        }
        int32_t newMtu = NetConstants::PossibleMtu[m_mtuIdx + 1];
        NetPacket *netPacket = NetPacketPool::GetInstance().getPacket(newMtu);
        netPacket->setProperty(PacketProperty::MtuCheck);
        NetUtils::Int32ToByte(&(netPacket->getRawData()[1]), newMtu);
        NetUtils::Int32ToByte(&(netPacket->getRawData()[netPacket->getPacketSize() - 4]), newMtu);

        m_netManager->sendNetPacketAndRecycle(netPacket, getEndpoint());
        m_finishMtu = true;
    }

    /***********************************************************************************************************
     * @brief 处理连接请求
    ***********************************************************************************************************/ 
    ConnectRequestResult NetPeer::processConnectRequest(NetConnectRequestPacket *connRequest)
    {
        switch (m_connectionState)
        {
        // P2P case
        case ConnectionState::Outgoing:
            // 未实现 ...
            break;
        case ConnectionState::Connected:
            // Old connect request
            if (connRequest->connectionTime == m_connectTime)
            {
                m_netManager->sendNetPacket(m_connectAcceptPacket, getEndpoint());
            }
            else if (connRequest->connectionTime > m_connectTime)
            {
                return ConnectRequestResult::Reconnection;
            }
            break;
        case ConnectionState::Disconnected:
        case ConnectionState::ShutdownRequested:
            if (connRequest->connectionTime >= m_connectTime)
            {
                return ConnectRequestResult::NewConnection;
            }
            break;
        }
        return ConnectRequestResult::None;
    }

    void NetPeer::processData(char *dataBuff, uint32_t dataSize)
    {
        if(m_connectionState == ConnectionState::Outgoing || m_connectionState == ConnectionState::Disconnected)
        {
            return;
        }

        if (NetPacket::GetProperty(dataBuff) == PacketProperty::ShutdownOk)
        {
            if (m_connectionState == ConnectionState::ShutdownRequested)
            {
                m_connectionState = ConnectionState::Disconnected;
            }
            return;
        }


        if(NetPacket::GetConnectionNumber(dataBuff) != m_connectNum)
        {
            NetDebug::Warn("LiteNetLib收到编号不一致的包: {} != {}", NetPacket::GetConnectionNumber(dataBuff), m_connectNum);
            return;
        }
        m_timeSinceLastPacket = 0;

        // NetDebug::Info("[RR]PacketProperty: {}", (uint8_t)packet->getProperty());
        switch (NetPacket::GetProperty(dataBuff))
        {
        case PacketProperty::Merged:
            {
                int32_t pos = NetConstants::HeaderSize;
                while (pos < dataSize)
                {
                    uint16_t size = NetUtils::ByteToUInt16(dataBuff + pos);
                    pos += 2;
                    if (dataSize - pos < size)
                    {
                        break;
                    }
                    if(NetPacket::Verify(dataBuff + pos, size) == false)
                    {
                        break;
                    }
                    processData(dataBuff + pos, size);
                    pos += size;
                }
            }
            break;
        case PacketProperty::Ping:
            if (NetUtils::RelativeSequenceNumber(NetPacket::GetSequence(dataBuff), m_pongPacket->getSequence()) > 0)
            {
                // NetDebug::Info("[PP]Ping receive, send pong");
                
                m_pongPacket->setSequence(NetPacket::GetSequence(dataBuff));
                NetUtils::UInt64ToByte(m_pongPacket->getRawData() + 3, UINT64_MAX);
                m_netManager->sendNetPacket(m_pongPacket, getEndpoint());
            }
            break;
        case PacketProperty::Pong:
            updateRoundTripTime(30);
            break;
        case PacketProperty::Ack:
        case PacketProperty::Channeled:
            {
                if (NetPacket::GetChannelId(dataBuff) > m_channels.size())
                {
                    break;
                }
                BaseChannel *channel = m_channels[NetPacket::GetChannelId(dataBuff)];
                if (channel == nullptr && NetPacket::GetProperty(dataBuff) == PacketProperty::Channeled)
                {
                    channel = createChannel(NetPacket::GetChannelId(dataBuff));
                }
                if (channel != nullptr)
                {
                    channel->processData(dataBuff, dataSize);
                }
            }
            break;
        case PacketProperty::Unreliable:
            {
                NetPacket *netPacket = NetPacketPool::GetInstance().getPacket(dataSize);
                memcpy(netPacket->getRawData(), dataBuff, dataSize);
                m_netManager->createReceiveEvent(netPacket, DeliveryMethod::Unreliable, NetConstants::HeaderSize, shared_from_this());
            }
            return;
        case PacketProperty::MtuCheck:
        case PacketProperty::MtuOk:
            processMtuData(dataBuff, dataSize);
            return;
        default:
            NetDebug::Error("Error! Unexpected packet type: {}", (uint8_t)NetPacket::GetProperty(dataBuff));
            break;
        }
    }

    /***********************************************************************************************************
     * @brief 发送合并的包
    ***********************************************************************************************************/ 
    void NetPeer::sendMerged()
    {
        if(m_mergeCount == 0)
        {
            return;
        }
        if(m_mergeCount > 1)
        {
            m_netManager->sendRaw(m_mergePacket->getRawData(), NetConstants::HeaderSize + m_mergePos, getEndpoint());
        }
        else
        {
            m_netManager->sendRaw(&(m_mergePacket->getRawData()[NetConstants::HeaderSize + 2]), m_mergePos - 2, getEndpoint());
        }
        m_mergePos = 0;
        m_mergeCount = 0;
    }


    void NetPeer::sendUserPacket(NetPacket *packet)
    {
        packet->setConnectionNumber(m_connectNum);
        int32_t mergedPacketSize = NetConstants::HeaderSize + packet->getPacketSize() + 2;
        const int32_t sizeTreshold = 20;
        if(mergedPacketSize + sizeTreshold >= m_mtu)
        {
            m_netManager->sendRaw(packet->getRawData(), packet->getPacketSize(), getEndpoint());
            return;
        }
        if(m_mergePos + mergedPacketSize > m_mtu)
        {
            sendMerged();
        }
        NetUtils::UInt16ToByte(&(m_mergePacket->getRawData()[m_mergePos + NetConstants::HeaderSize]), packet->getPacketSize());
        memcpy(&(m_mergePacket->getRawData()[m_mergePos + NetConstants::HeaderSize + 2]), packet->getRawData(), packet->getPacketSize());
        m_mergePos += packet->getPacketSize() + 2;
        m_mergeCount++;
    }


    void NetPeer::update(int32_t deltaTime)
    {
        m_timeSinceLastPacket += deltaTime;

        switch (m_connectionState)
        {
        case ConnectionState::Connected:
            if (m_timeSinceLastPacket > NetConstants::DisconnectTimeout)
            {
                // NetDebug::Info("[UPDATE] Disconnect by timeout: {} > {}", m_timeSinceLastPacket, m_netManager->disconnectTimeout);
                m_netManager->disconnectPeerForce(shared_from_this(), DisconnectReason::Timeout, nullptr);
                return;
            }
            break;
        case ConnectionState::ShutdownRequested:
            if (m_timeSinceLastPacket > m_netManager->disconnectTimeout)
            {
                m_connectionState = ConnectionState::Disconnected;
            }
            else
            {
                m_shutdownTime += deltaTime;
                if (m_shutdownTime >= shutdownDelay)
                {
                    m_shutdownTime = 0;
                    shutdown(nullptr, 0, false);
                }
            }
            return;
        case ConnectionState::Outgoing:
            return;
        case ConnectionState::Disconnected:
            return;
        }

        //Send ping
        m_pingSendTime += deltaTime;
        if (m_pingSendTime >= m_netManager->pingInterval)
        {
            // NetDebug::Info("[PP] Send ping...");
            m_pingSendTime = 0;
            m_pingPacket->setSequence(m_pingPacket->getSequence() + 1);
            m_netManager->sendNetPacket(m_pingPacket, getEndpoint());
        }

        // m_rttResetTime += deltaTime;
        // if (m_rttResetTime >= m_netManager->pingInterval *3)
        // {
        //     m_rttResetTime = 0;
        //     m_rtt = m_avgRtt;
        //     m_rttCount = 1;
        // }

        updateMtuLogic(deltaTime);

        BaseChannel *channel = nullptr;
        int32_t channelCount = m_channelSendQueue.size();
        while (channelCount > 0)
        {
            if(m_channelSendQueue.try_pop(channel) == false)
            {
                break;
            }
            if (channel->sendAndCheckQueue())
            {
                m_channelSendQueue.push(channel);
            }
            --channelCount;
        }
        NetPacket *netPacket = nullptr;
        while (m_unreliableChannel.try_pop(netPacket))
        {
            sendUserPacket(netPacket);
            NetPacketPool::GetInstance().recycleOrDelete(netPacket);
        }

        sendMerged();
    }


    /***********************************************************************************************************
     * @brief 发送数据
     * @param theData 数据
     * @param dataSize 数据的大小
     * @param channelNumber 使用的通道号
     * @param deliveryMethod 传输方式
    ***********************************************************************************************************/
    void NetPeer::sendInternal(const char *theData, uint32_t dataSize, uint8_t channelNumber, DeliveryMethod deliveryMethod)
    {
        if (m_connectionState != ConnectionState::Connected)
        {
            return;
        }
        // 通过传输方式选择通道号
        BaseChannel *baseChannel = nullptr;
        PacketProperty property;
        if (deliveryMethod == DeliveryMethod::Unreliable)
        {
            property = PacketProperty::Unreliable;
        }
        else
        {
            property = PacketProperty::Channeled;
            baseChannel = createChannel((uint8_t)(channelNumber * 4 + (uint8_t)deliveryMethod));
        }
        
        int32_t headerSize = NetPacket::GetHeaderSize(property);
        // 先获取单个包最大数据量，防止多线程导致出错
        int32_t mtu = m_mtu;
        // 数据包过大，拆包发送
        if(dataSize + headerSize > mtu)
        {
            if(baseChannel == nullptr)
            {
                throw std::logic_error("通道不存在，无法拆包");
            }
            if (deliveryMethod != DeliveryMethod::ReliableOrdered && deliveryMethod != DeliveryMethod::ReliableUnordered)
            {
                 throw std::logic_error(fmt::format("不可靠或可靠序列数据包大小超过最大值 {} 字节",(mtu - headerSize)));
            }
            int32_t packetFullSize = mtu - headerSize;
            int32_t packetDataSize = packetFullSize - NetConstants::FragmentHeaderSize;
            int32_t totalPackets = dataSize / packetDataSize + (dataSize % packetDataSize == 0 ? 0 : 1);
            if(totalPackets == 1)
            {
                NetDebug::Error("LiteNetLib分割包错误");
            }
            if(totalPackets > UINT16_MAX)
            {
                throw std::length_error("数据包过大");
            }
            uint16_t currentFragmentID = ++m_fragmentID;
            // NetDebug::Info("channel: {}, fragmentID: {}", channelNumber, currentFragmentID);

            for(uint16_t partIdx = 0; partIdx < totalPackets; partIdx++)
            {
                int32_t sendLength = dataSize > packetDataSize ? packetDataSize : dataSize;
                
                NetPacket *netPacketPart = NetPacketPool::GetInstance().getPacket(headerSize + sendLength + NetConstants::FragmentHeaderSize);
                netPacketPart->setProperty(property);
                netPacketPart->setFragmentId(currentFragmentID);
                netPacketPart->setFragmentPart(partIdx);
                netPacketPart->setFragmentsTotal(totalPackets);
                netPacketPart->markFragmented();

                memcpy(netPacketPart->getRawData() + NetConstants::FragmentedHeaderTotalSize, &(theData[partIdx * packetDataSize]), sendLength);
                baseChannel->addToQueue(netPacketPart);

                dataSize -= sendLength;
            }
            return;
        }

        NetPacket *netPacket = NetPacketPool::GetInstance().getPacket(headerSize + dataSize);
        netPacket->setProperty(property);
        memcpy(netPacket->getRawData() + headerSize, theData, dataSize);
        if (baseChannel == nullptr)
        {
            m_unreliableChannel.push(netPacket);
        }
        else
        {
            baseChannel->addToQueue(netPacket);
        }
    }

}